#include "client.hpp"
#include <sstream>
/**
	Constructeur de la classe
*/
Client::Client(const char* adresse)
{
	dport = 1888;
	activate = false;
	connected = false;

	hostInfo = gethostbyname(adresse);
	addressServer = (char*)adresse;
	
	if(hostInfo != NULL)
	{
		serverAddress.sin_family = hostInfo->h_addrtype;
		memcpy((char *) &serverAddress.sin_addr.s_addr, hostInfo->h_addr_list[0], hostInfo->h_length);
		serverAddress.sin_port = htons(dport);
	}
}
/**
	Démarre le client :
	On se connecte au serveur puis on entre dans la boucle
	d'exécution si la connexion a réussi : voir runLopp();
*/
void Client::start()
{
	activate = true;
	cout << "::Connexion au serveur " << addressServer;
	socketDesc = socket(AF_INET, SOCK_STREAM, 0);
	if(socketDesc <= 0)
	{
		cout << "\t\t\tEchoue!" << endl;
	}
	else
	{
		if(connect(socketDesc, (sockaddr*) &serverAddress, sizeof(sockaddr)) == -1)
		{
			cout << "\t\t\tEchoue!" << endl;
		}
		else
		{
			cout << "\t\t\tOK" << endl;
			/* init the list to listen */
			connected = true;
			runLoop();
		}
	}
}

/**
	Termine l'exécution
*/
void Client::stop()
{
	activate = false;

}

/**
	Traitement des données reçues sur le socket
*/
void Client::dataHandler()
{
	for(int k=0; k<BUFFSIZE; k++)
		buff[k] = '\0';
	if(FD_ISSET(socketDesc, &toListen))
	{
		int rec_res = recv(socketDesc, buff, BUFFSIZE, 0);
		if(rec_res == 0)
		{
			close(socketDesc);
			cout << "Deconnexion: Le serveur semble ne pas etre lance" << endl;
			stop();
		}
		else if(rec_res > 0)
		{
			FString req(buff);
			FString cmd = req.getCmd();
			FString arg = req.getArgs();

			if(cmd.compare("UPDATE") == 0)
			{
				if(arg.compare("ALL") == 0)
				{
					update();
				}
			}
			else
				cout << "Recu: " << buff << endl;
		}
	}
}
/**
	Traitement des données sur l'entrée standard
*/
void Client::stdinHandler()
{
	if(FD_ISSET(0, &toListen))
	{
		int rec_res = read(0, buff, BUFFSIZE);
		if(rec_res > 0)
		{
			// on enlève le '\n' à la fin
			for(int i=0; i<BUFFSIZE; i++)
			{
				if(buff[i] == '\n')
				{
					buff[i] = '\0';
					i = BUFFSIZE;
				}
			}

			if(strcmp("",buff) != 0)
			{
				processCmd(buff);
			}
		}
	}
}

/** 
	 Methode permettant d'envoyer un message et de se mettre en attente
*/
FString Client::sendAndWait(FString request)
{
	for(int k=0; k<BUFFSIZE; k++)
		buff[k] = '\0';
	send(socketDesc, request.data(), request.size(), 0);
	cout << "Attente du serveur..." << endl;
	recv(socketDesc, buff, BUFFSIZE, 0);

	return FString(buff);
}

/**
	Boucle d'exécution de l'application Client.
*/
void Client::runLoop()
{
	struct timeval timeout;
	while(activate)
	{
		showPrompt();
		for(int k=0; k<BUFFSIZE; k++)
			buff[k] = '\0';

		FD_ZERO(&toListen);
		FD_SET(socketDesc, &toListen);
		FD_SET(0, &toListen);
		int descMax = max(0, socketDesc);

		timeout.tv_sec = 1;
		timeout.tv_usec = 0;
		int sel_res = select(descMax+1, &toListen, NULL, NULL, NULL);

		if(sel_res > 0)
		{
			dataHandler();
			stdinHandler();
		}
	}
	connected = false;
}


void Client::update()
{
	FString str = sendAndWait("DETAILS ALL");	
}

/** 
	 Renvoie true si la connexion au serveur est active,
	 false sinon.
*/
bool Client::isConnected()
{
	return connected;
}

/**
	Destructeur
*/
Client::~Client()
{

}


